﻿using BTS;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.Practices.ESB.Adapter;
using Microsoft.Practices.ESB.Configuration;
using Microsoft.Practices.ESB.Exception.Management;
using Microsoft.Practices.ESB.GlobalPropertyContext;
using Microsoft.Practices.ESB.Itinerary;
//using Microsoft.Practices.ESB.Itinerary.OM.V1;
using Microsoft.Practices.ESB.Itinerary.OM.V2;
//using Microsoft.Practices.ESB.Itinerary.OM.V1.Properties;
using Microsoft.Practices.ESB.Itinerary.Schemas;
using Microsoft.Practices.ESB.Resolver;
using Microsoft.XLANGs.BaseTypes;
using Microsoft.XLANGs.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;

namespace BizTalk.ESB.Extensions.ItineraryOM
{
    //[Serializable]
    //public class ItineraryV2: ItineraryV1
    //{
    //    private static readonly string resolverDelimeter = "]]>";
    //    private static readonly string resolverStartInd = "<![CDATA[";
    //    private static readonly string resolverStrdelimeter = "]]&gt;";
    //    private static readonly string resolverStrStartInd = "&lt;![CDATA[";

    //    public new void Advance(XLANGMessage message, IItineraryStep step)
    //    {
    //        Action action2 = null;
    //        if (message == null)
    //        {
    //            throw new ArgumentNullException("message");
    //        }
    //        if (step == null)
    //        {
    //            throw new ArgumentNullException("step");
    //        }
    //        string state = string.Empty;
    //        try
    //        {
    //            if (this.ItineraryData.Services[step.Position] != null)
    //            {
    //                this.FinalizeStep(step);
    //                this.ItineraryData.ServiceInstance.nextId = step.NextId;
    //            }
    //            if (action2 == null)
    //            {
    //                action2 = delegate
    //                {
    //                    BAMItineraryProcess.SubmitToBAM(this.ItineraryData, step, message);
    //                };
    //            }
    //            Action submitToBam = action2;
    //            bool isRequestResponse = this.ItineraryData.ServiceInstance.isRequestResponse;
    //            if (!string.IsNullOrEmpty(this.ItineraryData.ServiceInstance.nextId))
    //            {
    //                // Updated the line below to use RootService.InstanceId instead of RootService.ServiceId
    //                state = this.AdvanceById(ItineraryMessageDirection.Unknown, Context.RootService.InstanceId.ToString(), step, submitToBam, true);
    //            }
    //            else
    //            {
    //                // Updated the line below to use RootService.InstanceId instead of RootService.ServiceId
    //                state = this.AdvanceByOrder(ItineraryMessageDirection.Unknown, Context.RootService.InstanceId.ToString(), step, submitToBam, true);
    //            }
    //            if (((step.State == Microsoft.Practices.ESB.Itinerary.State.Pending) && this.IsInvocationService(step)) && (step.ResolverCollection.Count > 0))
    //            {
    //                Microsoft.Practices.ESB.Adapter.AdapterMgr.SetEndpoint(ResolverMgr.Resolve(message, step.ResolverCollection[0]), message);
    //                isRequestResponse = this.ItineraryData.ServiceInstance.isRequestResponse;
    //            }
    //            else
    //            {
    //                message.SetPropertyValue(typeof(OutboundTransportLocation), "");
    //                message.SetPropertyValue(typeof(OutboundTransportType), "FILE");
    //            }
    //            this.SetCorrelationProperties(message, isRequestResponse);
    //            this.SetServiceProperties(message, state);
    //        }
    //        catch (Exception exception)
    //        {
    //            EventLogger.LogMessage(EventFormatter.FormatEvent(MethodBase.GetCurrentMethod(), exception), EventLogEntryType.Error, 0x17ca);
    //            throw;
    //        }
    //    }

    //    //public new void Advance(IBaseMessage message, IItineraryStep step)
    //    //{
    //    //}

    //    public new IItineraryStep GetItineraryStep(XLANGMessage message)
    //    {
    //        IItineraryStep step2;
    //        if (message == null)
    //        {
    //            throw new ArgumentNullException("message");
    //        }
    //        try
    //        {
    //            if (this.ItineraryData.state == Microsoft.Practices.ESB.Itinerary.State.Complete)
    //            {
    //                return null;
    //            }
    //            DefaultItineraryStep step = new DefaultItineraryStep();
    //            this.UpdateServiceInstanceSegment(this.ItineraryData.Services[this.ItineraryData.ServiceInstance.position].Service, this.ItineraryData.ServiceInstance.state);
    //            // Updated the line below to use RootService.InstanceId rather than RootService.ServiceId
    //            this.UpdateStep(ItineraryMessageDirection.Unknown, Context.RootService.InstanceId.ToString(), step, Microsoft.Practices.ESB.Itinerary.State.Pending);
    //            step.ResolverCollection.MsgGetEnumerator();
    //            step.Itinerary = this;
    //            step2 = step;
    //        }
    //        catch (Exception exception)
    //        {
    //            EventLogger.LogMessage(EventFormatter.FormatEvent(MethodBase.GetCurrentMethod(), exception), EventLogEntryType.Error, 0x17ca);
    //            throw;
    //        }
    //        return step2;
    //    }

    //    #region Copy of ItineraryV1 Private Methods

    //    private void SetCorrelationProperties(XLANGMessage message, bool setEpmRR)
    //    {
    //        string str = "Unknown:0";
    //        string str2 = "0";
    //        string str3 = "0";
    //        int num = 0;
    //        bool flag = false;
    //        string propertyValue = message.GetPropertyValue(typeof(CorrelationToken)) as string;
    //        string str5 = message.GetPropertyValue(typeof(ReqRespTransmitPipelineID)) as string;
    //        string str6 = message.GetPropertyValue(typeof(EpmRRCorrelationToken)) as string;
    //        object obj2 = message.GetPropertyValue(typeof(BTS.IsRequestResponse));
    //        message.GetPropertyValue(typeof(RouteDirectToTP));
    //        if (setEpmRR)
    //        {
    //            string[] strArray = this.ItineraryData.BizTalkSegment.epmRRCorrelationToken.Split("|".ToCharArray());
    //            if (strArray == null)
    //            {
    //                throw new ItinerarySetCorrelationException(0x71868);
    //            }
    //            if (strArray.GetUpperBound(0) != 2)
    //            {
    //                throw new ItinerarySetCorrelationException(0x71868);
    //            }
    //            str = strArray[0];
    //            str2 = strArray[1];
    //            str3 = strArray[2];
    //            num = 1;
    //            flag = true;
    //        }
    //        if (string.IsNullOrEmpty(str6) || (str6 == "Unknown:0"))
    //        {
    //            message.SetPropertyValue(typeof(EpmRRCorrelationToken), str);
    //        }
    //        if (obj2 == null)
    //        {
    //            message.SetPropertyValue(typeof(BTS.IsRequestResponse), num);
    //        }
    //        if (string.IsNullOrEmpty(propertyValue) || (propertyValue == "0"))
    //        {
    //            message.SetPropertyValue(typeof(CorrelationToken), str2);
    //        }
    //        if (string.IsNullOrEmpty(str5) || (str5 == "0"))
    //        {
    //            message.SetPropertyValue(typeof(ReqRespTransmitPipelineID), str3);
    //        }
    //        message.SetPropertyValue(typeof(RouteDirectToTP), flag);
    //    }

    //    private void SetServiceProperties(XLANGMessage message, string state)
    //    {
    //        message.SetPropertyValue(typeof(ServiceName), this.ItineraryData.ServiceInstance.name.Trim());
    //        message.SetPropertyValue(typeof(ServiceType), this.ItineraryData.ServiceInstance.type.Trim());
    //        message.SetPropertyValue(typeof(ServiceState), state);
    //        message.SetPropertyValue(typeof(Microsoft.Practices.ESB.Itinerary.Schemas.IsRequestResponse), this.ItineraryData.ServiceInstance.isRequestResponse);
    //    }

    //    private void FinalizeStep(IItineraryStep step)
    //    {
    //        if (this.ItineraryData.Services[step.Position] != null)
    //        {
    //            this.ItineraryData.Services[step.Position].Service.state = Microsoft.Practices.ESB.Itinerary.State.Complete;
    //            this.ItineraryData.Services[step.Position].Service.completeTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture);
    //            step.State = this.ItineraryData.Services[step.Position].Service.state;
    //            step.CompleteTime = this.ItineraryData.Services[step.Position].Service.completeTime;
    //            this.ItineraryData.Services[step.Position].Service.beginTime = step.BeginTime;
    //            this.ItineraryData.Services[step.Position].Service.serviceInstanceId = step.ServiceInstanceId;
    //        }
    //    }

    //    private string AdvanceByOrder(ItineraryMessageDirection messageDirection, string serviceInstanceId, IItineraryStep step, Action submitToBam, bool advanceStep)
    //    {
    //        string pending;
    //        if (serviceInstanceId == null)
    //        {
    //            serviceInstanceId = string.Empty;
    //        }
    //        if (submitToBam == null)
    //        {
    //            throw new ArgumentNullException("submitToBam");
    //        }
    //        if (step == null)
    //        {
    //            throw new ArgumentNullException("step");
    //        }
    //        try
    //        {
    //            int position = step.Position;
    //            if ((position + 1) < this.ItineraryData.servicecount)
    //            {
    //                this.UpdateServiceInstanceSegment(this.ItineraryData.Services[position + 1].Service, Microsoft.Practices.ESB.Itinerary.State.Pending);
    //                pending = Microsoft.Practices.ESB.Itinerary.State.Pending;
    //            }
    //            else
    //            {
    //                this.CompleteItinerary(this.ItineraryData.Services[position]);
    //                pending = Microsoft.Practices.ESB.Itinerary.State.Complete;
    //            }
    //            submitToBam();
    //            if (advanceStep)
    //            {
    //                this.UpdateStep(messageDirection, serviceInstanceId, step, pending);
    //            }
    //        }
    //        catch (Exception exception)
    //        {
    //            EventLogger.LogMessage(EventFormatter.FormatEvent(MethodBase.GetCurrentMethod(), exception), EventLogEntryType.Error, 0x17ca);
    //            throw;
    //        }
    //        return pending;
    //    }

    //    private string AdvanceById(ItineraryMessageDirection messageDirection, string serviceInstanceId, IItineraryStep step, Action submitToBam, bool advanceStep)
    //    {
    //        if (serviceInstanceId == null)
    //        {
    //            serviceInstanceId = string.Empty;
    //        }
    //        if (submitToBam == null)
    //        {
    //            throw new ArgumentNullException("submitToBam");
    //        }
    //        if (step == null)
    //        {
    //            throw new ArgumentNullException("step");
    //        }
    //        string state = string.Empty;
    //        try
    //        {
    //            if ((this.ItineraryData.ServiceInstance.nextId != Guid.Empty.ToString()) && (this.ItineraryData.ServiceInstance.nextId != "00000000000000000000000000000000"))
    //            {
    //                ItineraryServicesService service = this.ItineraryData.itineraryDictionary[this.ItineraryData.ServiceInstance.nextId];
    //                this.UpdateServiceInstanceSegment(service, Microsoft.Practices.ESB.Itinerary.State.Pending);
    //                state = Microsoft.Practices.ESB.Itinerary.State.Pending;
    //            }
    //            else
    //            {
    //                this.CompleteItinerary(this.ItineraryData.Services[step.Position]);
    //                state = Microsoft.Practices.ESB.Itinerary.State.Complete;
    //            }
    //            submitToBam();
    //            if (advanceStep)
    //            {
    //                this.UpdateStep(messageDirection, serviceInstanceId, step, state);
    //            }
    //        }
    //        catch (Exception exception)
    //        {
    //            EventLogger.LogMessage(EventFormatter.FormatEvent(MethodBase.GetCurrentMethod(), exception), EventLogEntryType.Error, 0x17ca);
    //            throw;
    //        }
    //        return state;
    //    }

    //    private void UpdateServiceInstanceSegment(ItineraryServicesService service, string state)
    //    {
    //        this.ItineraryData.ServiceInstance.name = service.name;
    //        if (service.isRequestResponseSpecified)
    //        {
    //            this.ItineraryData.ServiceInstance.isRequestResponseSpecified = true;
    //            this.ItineraryData.ServiceInstance.isRequestResponse = service.isRequestResponse;
    //        }
    //        this.ItineraryData.ServiceInstance.positionSpecified = true;
    //        this.ItineraryData.ServiceInstance.position = service.position;
    //        this.ItineraryData.ServiceInstance.state = state;
    //        this.ItineraryData.ServiceInstance.type = service.type;
    //        this.ItineraryData.ServiceInstance.uuid = service.uuid;
    //        this.ItineraryData.ServiceInstance.id = service.id;
    //        this.ItineraryData.ServiceInstance.nextId = service.nextId;
    //        if (service.stageSpecified)
    //        {
    //            this.ItineraryData.ServiceInstance.stageSpecified = true;
    //            this.ItineraryData.ServiceInstance.stage = service.stage;
    //        }
    //        else
    //        {
    //            this.ItineraryData.ServiceInstance.stageSpecified = false;
    //            this.ItineraryData.ServiceInstance.stage = Microsoft.Practices.ESB.Itinerary.OM.V1.Stages.notSpecified;
    //        }
    //    }

    //    private void CompleteItinerary(Microsoft.Practices.ESB.Itinerary.OM.V1.ItineraryServices service)
    //    {
    //        if (service != null)
    //        {
    //            this.ItineraryData.state = service.Service.state;
    //            this.ItineraryData.completeTime = service.Service.completeTime;
    //        }
    //        else
    //        {
    //            this.ItineraryData.completeTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture);
    //            this.ItineraryData.state = Microsoft.Practices.ESB.Itinerary.State.Complete;
    //        }
    //        this.ItineraryData.ServiceInstance.state = Microsoft.Practices.ESB.Itinerary.State.Complete;
    //    }

    //    private void UpdateStep(ItineraryMessageDirection messageDirection, string serviceInstanceId, IItineraryStep step, string state)
    //    {
    //        step.PropertyBag.Clear();
    //        step.MessageDirection = messageDirection;
    //        step.ServiceName = this.ItineraryData.ServiceInstance.name;
    //        step.Position = this.ItineraryData.ServiceInstance.position;
    //        step.IsRequestResponse = this.ItineraryData.ServiceInstance.isRequestResponse;
    //        step.ServiceType = (ItineraryServiceType)Enum.Parse(typeof(ItineraryServiceType), this.ItineraryData.ServiceInstance.type.Trim(), true);
    //        Microsoft.Practices.ESB.Itinerary.OM.V1.Stages stages = this.ItineraryData.ServiceInstance.stageSpecified ? this.ItineraryData.ServiceInstance.stage : Microsoft.Practices.ESB.Itinerary.OM.V1.Stages.notSpecified;
    //        step.Stage = (Microsoft.Practices.ESB.Itinerary.Stages)Enum.Parse(typeof(Microsoft.Practices.ESB.Itinerary.Stages), stages.ToString(), true);
    //        step.UUId = this.ItineraryData.ServiceInstance.uuid;
    //        step.Id = this.ItineraryData.ServiceInstance.id;
    //        step.NextId = this.ItineraryData.ServiceInstance.nextId;
    //        if (((step.Position < this.ItineraryData.Services.Length) && (this.ItineraryData.Services[step.Position].Service != null)) && (this.ItineraryData.Services[step.Position].Service.PropertyBag != null))
    //        {
    //            foreach (ItineraryServicesServiceProperty property in this.ItineraryData.Services[step.Position].Service.PropertyBag)
    //            {
    //                step.PropertyBag.Add(property.name, property.value);
    //            }
    //        }
    //        this.FillResolver(step);
    //        step.State = state;
    //        step.BeginTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture);
    //        step.ServiceInstanceId = serviceInstanceId;
    //        this.ItineraryData.ServiceInstance.state = state;
    //    }

    //    private void FillResolver(IItineraryStep step)
    //    {
    //        step.ResolverCollection.Clear();
    //        string id = step.ServiceName + step.Position.ToString();
    //        ItineraryResolvers resolvers = this.ItineraryData.ResolverGroups.Where<ItineraryResolvers>(delegate(ItineraryResolvers item)
    //        {
    //            return (item.serviceId == id);
    //        }).FirstOrDefault<ItineraryResolvers>();
    //        if (resolvers != null)
    //        {
    //            this.ParseResolversIntoStep(step, resolvers.Value);
    //        }
    //    }

    //    private void ParseResolversIntoStep(IItineraryStep step, string value)
    //    {
    //        if (value != null)
    //        {
    //            bool flag = true;
    //            while (flag)
    //            {
    //                int index = value.IndexOf(resolverDelimeter);
    //                if (index != -1)
    //                {
    //                    string str = value.Substring(0, index + resolverDelimeter.Length).Replace(resolverStartInd, "").Replace(resolverDelimeter, "").Replace("&amp;", "&");
    //                    if (str.Length > 1)
    //                    {
    //                        step.ResolverCollection.Add(str);
    //                    }
    //                    value = value.Substring(index + resolverDelimeter.Length).Trim();
    //                }
    //                else
    //                {
    //                    index = value.IndexOf(resolverStrdelimeter);
    //                    if (index != -1)
    //                    {
    //                        string str2 = value.Substring(0, index + resolverStrdelimeter.Length).Replace(resolverStrStartInd, "").Replace(resolverStrdelimeter, "").Replace("&amp;", "&");
    //                        if (str2.Length > 1)
    //                        {
    //                            step.ResolverCollection.Add(str2);
    //                        }
    //                        value = value.Substring(index + resolverStrdelimeter.Length).Trim();
    //                        continue;
    //                    }
    //                    flag = false;
    //                }
    //            }
    //        }
    //    }

    //    #endregion
    //}

    [Serializable]
    public class ItineraryV2 : IItinerary
    {
        #region Properties

        private static readonly string resolverDelimeter = "]]>";
        private static readonly string resolverStartInd = "<![CDATA[";
        private static readonly string resolverStrdelimeter = "]]&gt;";
        private static readonly string resolverStrStartInd = "&lt;![CDATA[";
        
        #endregion

        public void ActivateServiceInstance(IItineraryStep step)
        {
            if (step == null)
            {
                throw new ArgumentNullException("step");
            }
            step.State = State.Active;
        }

        public void Advance(XLANGMessage message, IItineraryStep step)
        {
            Action action2 = null;
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            if (step == null)
            {
                throw new ArgumentNullException("step");
            }
            string state = string.Empty;
            try
            {
                if (this.ItineraryData.Services[step.Position] != null)
                {
                    this.FinalizeStep(step);
                    this.ItineraryData.ServiceInstance.nextId = step.NextId;
                }
                if (action2 == null)
                {
                    action2 = delegate
                    {
                        BAMItineraryProcess.SubmitToBAM(this.ItineraryData, step, message);

                        // If tracking is enabled for any services in this itineary and this is the last service, end the itinerary "header" bam activity
                        if (this.ItineraryData.Services.Count(i => i.Service.isTrackingEnabled == true) > 0
                            && this.ItineraryData.ServiceInstance.nextId == "00000000000000000000000000000000")
                        {
                            EventLogger.Write(string.Format("ItineraryV2 - {0} is the last step, nextId = {1}.  Calling FinishItinerary"
                                , this.ItineraryData.ServiceInstance.name, this.ItineraryData.ServiceInstance.nextId));
                            BAMItineraryProcess.FinishItineraryBAM(this.ItineraryData, message);
                        }
                        else
                        {
                            EventLogger.Write(string.Format("ItineraryV2 - {0} is the current step, nextId = {1}.  Proceeding to next step.."
                                , this.ItineraryData.ServiceInstance.name, this.ItineraryData.ServiceInstance.nextId));
                        }
                    };
                }
                Action submitToBam = action2;
                bool isRequestResponse = this.ItineraryData.ServiceInstance.isRequestResponse;
                if (!string.IsNullOrEmpty(this.ItineraryData.ServiceInstance.nextId))
                {
                    // Updated the line below to use RootService.InstanceId instead of RootService.ServiceId
                    state = this.AdvanceById(ItineraryMessageDirection.Unknown, Context.RootService.InstanceId.ToString(), step, submitToBam, true);
                }
                else
                {
                    // Updated the line below to use RootService.InstanceId instead of RootService.ServiceId
                    state = this.AdvanceByOrder(ItineraryMessageDirection.Unknown, Context.RootService.InstanceId.ToString(), step, submitToBam, true);
                }
                if (((step.State == Microsoft.Practices.ESB.Itinerary.State.Pending) && this.IsInvocationService(step)) && (step.ResolverCollection.Count > 0))
                {
                    Microsoft.Practices.ESB.Adapter.AdapterMgr.SetEndpoint(ResolverMgr.Resolve(message, step.ResolverCollection[0]), message);
                    isRequestResponse = this.ItineraryData.ServiceInstance.isRequestResponse;
                }
                else
                {
                    message.SetPropertyValue(typeof(OutboundTransportLocation), "");
                    message.SetPropertyValue(typeof(OutboundTransportType), "FILE");
                }
                this.SetCorrelationProperties(message, isRequestResponse);
                this.SetServiceProperties(message, state);
            }
            catch (Exception exception)
            {
                EventLogger.LogMessage(EventFormatter.FormatEvent(MethodBase.GetCurrentMethod(), exception), EventLogEntryType.Error, 0x17ca);
                throw;
            }
        }

        public void Advance(IBaseMessage message, IPipelineContext context, IItineraryStep step, bool advanceStep)
        {
            Action action2 = null;

            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (step == null)
            {
                throw new ArgumentNullException("step");
            }

            EventLogger.Write(string.Format("Executing Advance() for messaging service: ID = {0}, position = {1}, UUID = {2}, service name = {3}, state = {4}, nextId = {5}"
                , step.Id, step.Position.ToString(), step.UUId.ToString(), step.ServiceName, step.State, step.NextId.ToString()));
            //EventLogger.Write(string.Format("Executing Advance()...current service: ID = {0}, position = {1}, UUID = {2}, service name = {3}, state = {4}, nextId = {5}"
            //    , this.ItineraryData.ServiceInstance.id, this.ItineraryData.ServiceInstance.position.ToString(), this.ItineraryData.ServiceInstance.uuid.ToString()
            //    , this.ItineraryData.ServiceInstance.name, this.ItineraryData.ServiceInstance.state, this.ItineraryData.ServiceInstance.nextId.ToString()));

            string state = string.Empty;
            try
            {
                if (this.ItineraryData.Services[step.Position] != null)
                {
                    this.FinalizeStep(step);
                    this.ItineraryData.ServiceInstance.nextId = step.NextId;
                }
                if (action2 == null)
                {
                    action2 = delegate
                    {
                        BAMItineraryProcess.SubmitToBAM(this.ItineraryData, step, context, message);

                        // If tracking is enabled for any services in this itineary and this is the last service, end the itinerary "header" bam activity
                        if (this.ItineraryData.Services.Count(i => i.Service.isTrackingEnabled == true) > 0
                            && this.ItineraryData.ServiceInstance.nextId == "00000000000000000000000000000000")
                        {
                            EventLogger.Write(string.Format("ItineraryV2 - {0} is the last step, nextId = {1}.  Calling FinishItinerary"
                                , this.ItineraryData.ServiceInstance.name, this.ItineraryData.ServiceInstance.nextId));
                            BAMItineraryProcess.FinishItineraryBAM(this.ItineraryData, message);
                        }
                        else
                        {
                            EventLogger.Write(string.Format("ItineraryV2 - {0} is the current step, nextId = {1}.  Proceeding to next step.."
                                , this.ItineraryData.ServiceInstance.name, this.ItineraryData.ServiceInstance.nextId));
                        }
                    };
                }
                Action submitToBam = action2;
                if (!string.IsNullOrEmpty(this.ItineraryData.ServiceInstance.nextId))
                {
                    state = this.AdvanceById(ItineraryHelper.MessageDirection(message), GetServiceInstanceId(message, step), step, submitToBam, advanceStep);
                    EventLogger.Write("Advanced to service with id " + step.Id);
                }
                else
                {
                    state = this.AdvanceByOrder(ItineraryHelper.MessageDirection(message), GetServiceInstanceId(message, step), step, submitToBam, advanceStep);
                    EventLogger.Write("Advanced to service with position " + step.Position);
                }
                this.SetServiceProperties(message, state);
            }
            catch (Exception exception)
            {
                EventLogger.LogMessage(EventFormatter.FormatEvent(MethodBase.GetCurrentMethod(), exception), EventLogEntryType.Error, 0x17ca);
                throw;
            }
        }

        public void Advance(IBaseMessage message, IPipelineContext context, IItineraryStep step)
        {
            this.Advance(message, context, step, true);
        }

        public IItineraryStep GetItineraryStep(XLANGMessage message)
        {
            IItineraryStep step2;
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            try
            {
                if (this.ItineraryData.state == State.Complete)
                {
                    return null;
                }
                DefaultItineraryStep step = new DefaultItineraryStep();
                this.UpdateServiceInstanceSegment(this.ItineraryData.Services[this.ItineraryData.ServiceInstance.position].Service, this.ItineraryData.ServiceInstance.state);
                // Updated the line below to use RootService.InstanceId rather than RootService.ServiceId
                this.UpdateStep(ItineraryMessageDirection.Unknown, Context.RootService.InstanceId.ToString(), step, Microsoft.Practices.ESB.Itinerary.State.Pending);
                step.ResolverCollection.MsgGetEnumerator();
                step.Itinerary = this;
                step2 = step;
            }
            catch (Exception exception)
            {
                EventLogger.LogMessage(EventFormatter.FormatEvent(MethodBase.GetCurrentMethod(), exception), EventLogEntryType.Error, 0x17ca);
                throw;
            }
            return step2;
        }

        public IItineraryStep GetItineraryStep(IBaseMessage message)
        {
            IItineraryStep step2;
            if (message == null)
            {
                throw new ArgumentNullException("message");
            }
            try
            {
                if (this.ItineraryData.state == State.Complete)
                {
                    return null;
                }
                DefaultItineraryStep step = new DefaultItineraryStep();
                this.UpdateServiceInstanceSegment(this.ItineraryData.Services[this.ItineraryData.ServiceInstance.position].Service, this.ItineraryData.ServiceInstance.state);
                this.UpdateStep(ItineraryHelper.MessageDirection(message), GetServiceInstanceId(message, step), step, Microsoft.Practices.ESB.Itinerary.State.Pending);
                step.ResolverCollection.MsgGetEnumerator();
                step.Itinerary = this;
                step2 = step;
            }
            catch (Exception exception)
            {
                EventLogger.LogMessage(EventFormatter.FormatEvent(MethodBase.GetCurrentMethod(), exception), EventLogEntryType.Error, 0x17ca);
                throw;
            }
            return step2;
        }

        public bool HasNextService()
        {
            if (!string.IsNullOrEmpty(this.ItineraryData.ServiceInstance.nextId))
            {
                return (this.ItineraryData.ServiceInstance.nextId != "00000000000000000000000000000000");
            }
            int index = this.ItineraryData.ServiceInstance.position + 1;
            return (((index < this.ItineraryData.servicecount) && (index < this.ItineraryData.Services.Length)) && (this.ItineraryData.Services[index].Service.state != State.Complete));
        }

        public bool HasNextServiceAsReceiveInbound()
        {
            return this.HasNextService(Microsoft.Practices.ESB.Itinerary.OM.V2.Stages.receiveInbound);
        }

        public bool HasNextServiceAsReceiveTransmit()
        {
            return this.HasNextService(Microsoft.Practices.ESB.Itinerary.OM.V2.Stages.receiveTransmit);
        }

        public bool HasNextServiceAsSendInbound()
        {
            return this.HasNextService(Microsoft.Practices.ESB.Itinerary.OM.V2.Stages.sendInbound);
        }

        public bool HasNextServiceAsSendTrasmit()
        {
            return this.HasNextService(Microsoft.Practices.ESB.Itinerary.OM.V2.Stages.sendTransmit);
        }

        public void Initialize(IBaseMessage msg, string uuid)
        {
            try
            {
                if (string.IsNullOrEmpty(this.ItineraryData.uuid))
                {
                    this.ItineraryData.uuid = uuid;
                }
                this.ItineraryData.beginTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture);
                this.ItineraryData.completeTime = "";
                this.ItineraryData.servicecount = this.ItineraryData.Services.Length;
                if (this.ItineraryData.BizTalkSegment == null)
                {
                    this.ItineraryData.BizTalkSegment = new ItineraryBizTalkSegment();
                }
                string str = msg.Context.Read(BtsProperties.CorrelationToken.Name, BtsProperties.CorrelationToken.Namespace) as string;
                string str2 = msg.Context.Read(BtsProperties.ReqRespTransmitPipelineID.Name, BtsProperties.ReqRespTransmitPipelineID.Namespace) as string;
                string str3 = msg.Context.Read(BtsProperties.InterchangeID.Name, BtsProperties.InterchangeID.Namespace) as string;
                string str4 = msg.Context.Read("ReceiveInstanceID", BtsProperties.InterchangeID.Namespace) as string;
                string str5 = msg.Context.Read(BtsProperties.MessageID.Name, BtsProperties.MessageID.Namespace) as string;
                string str6 = msg.Context.Read(BtsProperties.EpmRRCorrelationToken.Name, BtsProperties.EpmRRCorrelationToken.Namespace) as string;
                str6 = str6 + "|" + str + "|" + str2;
                this.ItineraryData.BizTalkSegment.epmRRCorrelationToken = str6 ?? "";
                this.ItineraryData.BizTalkSegment.receiveInstanceId = str4 ?? "";
                this.ItineraryData.BizTalkSegment.messageId = str5 ?? "";
                this.ItineraryData.BizTalkSegment.interchangeId = str3 ?? "";

                if (this.ItineraryData.ServiceInstance == null)
                {
                    this.ItineraryData.ServiceInstance = new ItineraryServiceInstance();
                    ItineraryServicesService service = this.ItineraryData.Services
                        .Where<Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices>(s => s.Service.state != State.Complete)
                        .Select<Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices, ItineraryServicesService>(s => s.Service)
                        .FirstOrDefault<ItineraryServicesService>();
                    if (service != null)
                    {
                        this.ItineraryData.ServiceInstance.id = service.id;
                        this.ItineraryData.ServiceInstance.name = service.name;
                        this.ItineraryData.ServiceInstance.position = service.position;
                        this.ItineraryData.ServiceInstance.positionSpecified = service.positionSpecified;
                        this.ItineraryData.ServiceInstance.stage = service.stage;
                        this.ItineraryData.ServiceInstance.stageSpecified = service.stageSpecified;
                        this.ItineraryData.ServiceInstance.state = service.state;
                    }
                }
                object obj2 = msg.Context.Read(BtsProperties.IsRequestResponse.Name, BtsProperties.IsRequestResponse.Namespace);
                if (obj2 != null)
                {
                    bool flag = Convert.ToBoolean(obj2);
                    this.ItineraryData.ServiceInstance.isRequestResponse = flag;
                    this.ItineraryData.ServiceInstance.isRequestResponseSpecified = true;
                }
                else
                {
                    this.ItineraryData.ServiceInstance.isRequestResponse = false;
                    this.ItineraryData.ServiceInstance.isRequestResponseSpecified = true;
                }
            }
            catch (Exception exception)
            {
                EventLogger.Write(MethodBase.GetCurrentMethod(), exception);
                throw;
            }
        }

        public bool IsInvocationService(IItineraryStep step)
        {
            if (step.ServiceType == ItineraryServiceType.Orchestration)
            {
                return false;
            }
            bool flag = false;
            if (step.ServiceType == ItineraryServiceType.Invocation)
            {
                flag = true;
            }
            if ((ConfigHelper.FindServiceByName(step.ServiceName, Scope.All) == null) && (step.ServiceType == ItineraryServiceType.Messaging))
            {
                flag = true;
            }
            return flag;
        }

        public Itinerary ItineraryData
        {
            get;
            set;
        }

        public void Read(string itineraryContents)
        {
            if (string.IsNullOrEmpty(itineraryContents))
            {
                throw new ArgumentNullException("itineraryContents");
            }
            try
            {
                using (System.IO.StringReader reader = new System.IO.StringReader(itineraryContents))
                {
                    //var serializer = new System.Xml.Serialization.XmlSerializer(typeof(Microsoft.Practices.ESB.Itinerary.OM.V1.Itinerary));
                    var serializer = new System.Xml.Serialization.XmlSerializer(typeof(BizTalk.ESB.Extensions.ItineraryOM.Itinerary));
                    this.ItineraryData = (Itinerary)serializer.Deserialize(reader);
                    if (this.ItineraryData.activityId == null)
                    {
                        this.ItineraryData.activityId = Guid.NewGuid().ToString();
                    }
                    reader.Close();
                }
                this.ItineraryData.Initialize();
            }
            catch (Exception exception)
            {
                EventLogger.Write(MethodBase.GetCurrentMethod(), exception);
                throw;
            }
        }

        public string ReadProperty(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            ItineraryProperty property = this.FindProperty(name);
            if (property == null)
            {
                return null;
            }
            return property.value;
        }

        public void RemoveProperty(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            if ((this.ItineraryData.PropertyBag != null) && (this.ItineraryData.PropertyBag.Length != 0))
            {
                for (int i = 0; i < this.ItineraryData.PropertyBag.Length; i++)
                {
                    ItineraryProperty property = this.ItineraryData.PropertyBag[i];
                    if ((property != null) && (string.Compare(name, property.name, true) == 0))
                    {
                        this.ItineraryData.PropertyBag[i] = null;
                        return;
                    }
                }
            }
        }

        public void Validate()
        {
            if (this.ItineraryData.servicecount != this.ItineraryData.Services.Length)
            {
                throw new ItineraryOMException(BizTalk.ESB.Extensions.ItineraryOM.Properties.Resources.ServiceCountMisMatch, new object[] { this.ItineraryData.servicecount, this.ItineraryData.Services.Length });
            }
            if ((this.ItineraryData.ServiceInstance.id != null) && !(this.ItineraryData.ServiceInstance.id == Guid.Empty.ToString()))
            {
                this.ValidateIds();
            }
            else
            {
                ItineraryServicesService result = this.ItineraryData.Services.Where<Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices>(delegate(Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices service)
                {
                    return (service.Service.state != Microsoft.Practices.ESB.Itinerary.State.Complete);
                }).Select<Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices, ItineraryServicesService>(delegate(Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices service)
                {
                    return service.Service;
                }).FirstOrDefault<ItineraryServicesService>();
                this.ValidateServiceInstance(result);
            }
            DefaultItineraryStep step = new DefaultItineraryStep();
            foreach (Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices services in this.ItineraryData.Services)
            {
                if ((services != null) && (services.Service != null))
                {
                    this.ValidateService(services.Service);
                    this.ValidateResolver(step, services);
                }
            }
        }

        public void Write(XLANGMessage msg)
        {
            if (msg == null)
            {
                throw new ArgumentNullException("msg");
            }
            try
            {
                msg.SetPropertyValue(typeof(ItineraryHeader), this.SerializeToString());
            }
            catch (Exception exception)
            {
                EventLogger.Write(MethodBase.GetCurrentMethod(), exception);
                throw;
            }
        }

        public void Write(IBaseMessage msg)
        {
            if (msg == null)
            {
                throw new ArgumentNullException("msg");
            }
            try
            {
                msg.Context.Write(ItineraryProperties.ItineraryHeader.Name, ItineraryProperties.ItineraryHeader.Namespace, this.SerializeToString());
                System.Diagnostics.Debug.WriteLine("ItineraryV2 - Wrote Itinerary to Message Context");

                if (this.ItineraryData.ServiceInstance != null)
                {
                    EventLogger.Write(string.Format("ItineraryV2 - Current Service Instance: name = {0}, type = {1}, isRequestResponse = {2}"
                        , this.ItineraryData.ServiceInstance.name, this.ItineraryData.ServiceInstance.type, this.ItineraryData.ServiceInstance.isRequestResponse));
                    this.SetServiceProperties(msg, this.ItineraryData.ServiceInstance.state);

                    // If tracking is enabled for any services in this itineary, start the itinerary "header" bam activity
                    if (this.ItineraryData.Services.Count(i => i.Service.isTrackingEnabled == true) > 0
                        && this.ItineraryData.ServiceInstance.position == 0)
                    {
                        BAMItineraryProcess.StartItineraryBAM(this.ItineraryData, msg);
                        if (!string.IsNullOrEmpty(this.ItineraryData.correlationId))
                        {
                            BAMItineraryProcess.UpdateItineraryBAM(this.ItineraryData, msg);
                        }
                    }
                }
                else
                {
                    throw new ItineraryException("Current Service instance is null.  Thrown from ItineraryV2.Write(IBaseMessage msg).");
                }
            }
            catch (Exception exception)
            {
                EventLogger.Write(MethodBase.GetCurrentMethod(), exception);
                throw;
            }
        }

        public void WriteProperty(string name, string value)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }
            ItineraryProperty property = this.FindProperty(name);
            if (property != null)
            {
                property.value = value;
            }
            else
            {
                this.AddPropertyToEnd(name, value);
            }
        }

        #region Private Methods

        private string SerializeToString()
        {
            string str;
            XmlSerializer serializer = new XmlSerializer(typeof(Itinerary));
            using (MemoryStream stream = new MemoryStream())
            {
                using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
                {
                    serializer.Serialize((Stream)stream, this.ItineraryData);
                    stream.Seek(0L, SeekOrigin.Begin);
                    str = reader.ReadToEnd();
                }
            }
            //Trace.WriteLine("ItineraryV2 - Serialized Itinerary to XML: " + str);
            return str;
        }

        private void AddPropertyToEnd(string name, string value)
        {
            if (this.ItineraryData.PropertyBag == null)
            {
                this.ItineraryData.PropertyBag = new ItineraryProperty[0];
            }
            ItineraryProperty[] destinationArray = new ItineraryProperty[this.ItineraryData.PropertyBag.Length + 1];
            System.Array.Copy(this.ItineraryData.PropertyBag, destinationArray, this.ItineraryData.PropertyBag.Length);
            ItineraryProperty property = new ItineraryProperty();
            property.name = name;
            property.value = value;
            destinationArray[this.ItineraryData.PropertyBag.Length] = property;
            this.ItineraryData.PropertyBag = destinationArray;
        }

        private static string GetServiceInstanceId(IBaseMessage message, IItineraryStep step)
        {
            string str = string.Empty;
            switch (step.MessageDirection)
            {
                case ItineraryMessageDirection.ReceiveInbound:
                case ItineraryMessageDirection.ReceiveTransmit:
                    return (message.Context.Read("ReceiveInstanceID", BtsProperties.InterchangeID.Namespace) as string);
                case ItineraryMessageDirection.SendInbound:
                case ItineraryMessageDirection.SendTransmit:
                    return (message.Context.Read(MessageTrackingProperties.ActivityIdentity.Name, MessageTrackingProperties.ActivityIdentity.Namespace) as string);
            }
            return str;
        }

        private void SetCorrelationProperties(XLANGMessage message, bool setEpmRR)
        {
            string str = "Unknown:0";
            string str2 = "0";
            string str3 = "0";
            int num = 0;
            bool flag = false;
            string propertyValue = message.GetPropertyValue(typeof(CorrelationToken)) as string;
            string str5 = message.GetPropertyValue(typeof(ReqRespTransmitPipelineID)) as string;
            string str6 = message.GetPropertyValue(typeof(EpmRRCorrelationToken)) as string;
            object obj2 = message.GetPropertyValue(typeof(BTS.IsRequestResponse));
            message.GetPropertyValue(typeof(RouteDirectToTP));
            if (setEpmRR)
            {
                string[] strArray = this.ItineraryData.BizTalkSegment.epmRRCorrelationToken.Split("|".ToCharArray());
                if (strArray == null)
                {
                    throw new ItinerarySetCorrelationException(0x71868);
                }
                if (strArray.GetUpperBound(0) != 2)
                {
                    throw new ItinerarySetCorrelationException(0x71868);
                }
                str = strArray[0];
                str2 = strArray[1];
                str3 = strArray[2];
                num = 1;
                flag = true;
            }
            if (string.IsNullOrEmpty(str6) || (str6 == "Unknown:0"))
            {
                message.SetPropertyValue(typeof(EpmRRCorrelationToken), str);
            }
            if (obj2 == null)
            {
                message.SetPropertyValue(typeof(BTS.IsRequestResponse), num);
            }
            if (string.IsNullOrEmpty(propertyValue) || (propertyValue == "0"))
            {
                message.SetPropertyValue(typeof(CorrelationToken), str2);
            }
            if (string.IsNullOrEmpty(str5) || (str5 == "0"))
            {
                message.SetPropertyValue(typeof(ReqRespTransmitPipelineID), str3);
            }
            message.SetPropertyValue(typeof(RouteDirectToTP), flag);
        }

        private void SetServiceProperties(XLANGMessage message, string state)
        {
            message.SetPropertyValue(typeof(ServiceName), this.ItineraryData.ServiceInstance.name.Trim());
            message.SetPropertyValue(typeof(ServiceType), this.ItineraryData.ServiceInstance.type.Trim());
            message.SetPropertyValue(typeof(ServiceState), state);
            message.SetPropertyValue(typeof(Microsoft.Practices.ESB.Itinerary.Schemas.IsRequestResponse), this.ItineraryData.ServiceInstance.isRequestResponse);
        }

        private void SetServiceProperties(IBaseMessage message, string state)
        {
            message.Context.Promote(ItineraryProperties.ServiceName.Name, ItineraryProperties.ServiceName.Namespace, this.ItineraryData.ServiceInstance.name.Trim());
            message.Context.Promote(ItineraryProperties.ServiceState.Name, ItineraryProperties.ServiceState.Namespace, state);
            message.Context.Promote(ItineraryProperties.ServiceType.Name, ItineraryProperties.ServiceType.Namespace, this.ItineraryData.ServiceInstance.type.Trim());
            message.Context.Promote(ItineraryProperties.IsRequestResponse.Name, ItineraryProperties.IsRequestResponse.Namespace, this.ItineraryData.ServiceInstance.isRequestResponse);
        }

        private void FinalizeStep(IItineraryStep step)
        {
            if (this.ItineraryData.Services[step.Position] != null)
            {
                EventLogger.Write(string.Format("ItineraryV2 - Starting Finalizing step {0}. State = {1}.", step.ServiceName, step.State));
                this.ItineraryData.Services[step.Position].Service.state = Microsoft.Practices.ESB.Itinerary.State.Complete;
                this.ItineraryData.Services[step.Position].Service.completeTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture);
                step.State = this.ItineraryData.Services[step.Position].Service.state;
                step.CompleteTime = this.ItineraryData.Services[step.Position].Service.completeTime;
                this.ItineraryData.Services[step.Position].Service.beginTime = step.BeginTime;
                this.ItineraryData.Services[step.Position].Service.serviceInstanceId = step.ServiceInstanceId;
                EventLogger.Write(string.Format("ItineraryV2 - Completed Finalizing step {0}. State = {1}.", step.ServiceName, step.State));
            }
        }

        private string AdvanceByOrder(ItineraryMessageDirection messageDirection, string serviceInstanceId, IItineraryStep step, Action submitToBam, bool advanceStep)
        {
            string pending;
            if (serviceInstanceId == null)
            {
                serviceInstanceId = string.Empty;
            }
            if (submitToBam == null)
            {
                throw new ArgumentNullException("submitToBam");
            }
            if (step == null)
            {
                throw new ArgumentNullException("step");
            }
            try
            {
                int position = step.Position;
                if ((position + 1) < this.ItineraryData.servicecount)
                {
                    this.UpdateServiceInstanceSegment(this.ItineraryData.Services[position + 1].Service, Microsoft.Practices.ESB.Itinerary.State.Pending);
                    pending = Microsoft.Practices.ESB.Itinerary.State.Pending;
                }
                else
                {
                    this.CompleteItinerary(this.ItineraryData.Services[position]);
                    pending = Microsoft.Practices.ESB.Itinerary.State.Complete;
                }
                submitToBam();
                if (advanceStep)
                {
                    this.UpdateStep(messageDirection, serviceInstanceId, step, pending);
                }
            }
            catch (Exception exception)
            {
                EventLogger.LogMessage(EventFormatter.FormatEvent(MethodBase.GetCurrentMethod(), exception), EventLogEntryType.Error, 0x17ca);
                throw;
            }
            return pending;
        }

        private string AdvanceById(ItineraryMessageDirection messageDirection, string serviceInstanceId, IItineraryStep step, Action submitToBam, bool advanceStep)
        {
            if (serviceInstanceId == null)
            {
                serviceInstanceId = string.Empty;
            }
            if (submitToBam == null)
            {
                throw new ArgumentNullException("submitToBam");
            }
            if (step == null)
            {
                throw new ArgumentNullException("step");
            }
            string state = string.Empty;
            try
            {
                EventLogger.Write(string.Format("ItineraryV2 - AdvanceById() - ServiceInstance.nextId = {0}", this.ItineraryData.ServiceInstance.nextId));
                if ((this.ItineraryData.ServiceInstance.nextId != Guid.Empty.ToString()) && (this.ItineraryData.ServiceInstance.nextId != "00000000000000000000000000000000"))
                {
                    ItineraryServicesService service = this.ItineraryData.itineraryDictionary[this.ItineraryData.ServiceInstance.nextId];
                    this.UpdateServiceInstanceSegment(service, Microsoft.Practices.ESB.Itinerary.State.Pending);
                    state = Microsoft.Practices.ESB.Itinerary.State.Pending;
                }
                else
                {
                    this.CompleteItinerary(this.ItineraryData.Services[step.Position]);
                    state = Microsoft.Practices.ESB.Itinerary.State.Complete;
                }
                submitToBam();
                if (advanceStep)
                {
                    this.UpdateStep(messageDirection, serviceInstanceId, step, state);
                }
            }
            catch (Exception exception)
            {
                EventLogger.LogMessage(EventFormatter.FormatEvent(MethodBase.GetCurrentMethod(), exception), EventLogEntryType.Error, 0x17ca);
                throw;
            }
            return state;
        }

        private void UpdateServiceInstanceSegment(ItineraryServicesService service, string state)
        {
            this.ItineraryData.ServiceInstance.name = service.name;
            if (service.isRequestResponseSpecified)
            {
                this.ItineraryData.ServiceInstance.isRequestResponseSpecified = true;
                this.ItineraryData.ServiceInstance.isRequestResponse = service.isRequestResponse;
            }
            this.ItineraryData.ServiceInstance.positionSpecified = true;
            this.ItineraryData.ServiceInstance.position = service.position;
            this.ItineraryData.ServiceInstance.state = state;
            this.ItineraryData.ServiceInstance.type = service.type;
            this.ItineraryData.ServiceInstance.uuid = service.uuid;
            this.ItineraryData.ServiceInstance.id = service.id;
            this.ItineraryData.ServiceInstance.nextId = service.nextId;
            if (service.stageSpecified)
            {
                this.ItineraryData.ServiceInstance.stageSpecified = true;
                this.ItineraryData.ServiceInstance.stage = service.stage;
            }
            else
            {
                this.ItineraryData.ServiceInstance.stageSpecified = false;
                this.ItineraryData.ServiceInstance.stage = Microsoft.Practices.ESB.Itinerary.OM.V2.Stages.notSpecified;
            }
        }

        private void CompleteItinerary(Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices service)
        {
            Trace.WriteLine("ItineraryV2 - CompleteItinerary()...");
            if (service != null)
            {
                this.ItineraryData.state = service.Service.state;
                this.ItineraryData.completeTime = service.Service.completeTime;
            }
            else
            {
                this.ItineraryData.completeTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture);
                this.ItineraryData.state = Microsoft.Practices.ESB.Itinerary.State.Complete;
            }
            this.ItineraryData.ServiceInstance.state = Microsoft.Practices.ESB.Itinerary.State.Complete;
        }

        private void UpdateStep(ItineraryMessageDirection messageDirection, string serviceInstanceId, IItineraryStep step, string state)
        {
            step.PropertyBag.Clear();
            step.MessageDirection = messageDirection;
            step.ServiceName = this.ItineraryData.ServiceInstance.name;
            step.Position = this.ItineraryData.ServiceInstance.position;
            step.IsRequestResponse = this.ItineraryData.ServiceInstance.isRequestResponse;
            step.ServiceType = (ItineraryServiceType)Enum.Parse(typeof(ItineraryServiceType), this.ItineraryData.ServiceInstance.type.Trim(), true);
            Microsoft.Practices.ESB.Itinerary.OM.V2.Stages stages = this.ItineraryData.ServiceInstance.stageSpecified ? this.ItineraryData.ServiceInstance.stage : Microsoft.Practices.ESB.Itinerary.OM.V2.Stages.notSpecified;
            step.Stage = (Microsoft.Practices.ESB.Itinerary.Stages)Enum.Parse(typeof(Microsoft.Practices.ESB.Itinerary.Stages), stages.ToString(), true);
            step.UUId = this.ItineraryData.ServiceInstance.uuid;
            step.Id = this.ItineraryData.ServiceInstance.id;
            step.NextId = this.ItineraryData.ServiceInstance.nextId;
            if (((step.Position < this.ItineraryData.Services.Length) && (this.ItineraryData.Services[step.Position].Service != null)) && (this.ItineraryData.Services[step.Position].Service.PropertyBag != null))
            {
                foreach (ItineraryServicesServiceProperty property in this.ItineraryData.Services[step.Position].Service.PropertyBag)
                {
                    step.PropertyBag.Add(property.name, property.value);
                }
            }
            this.FillResolver(step);
            step.State = state;
            step.BeginTime = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture);
            step.ServiceInstanceId = serviceInstanceId;
            this.ItineraryData.ServiceInstance.state = state;
        }

        private void FillResolver(IItineraryStep step)
        {
            step.ResolverCollection.Clear();
            string id = step.ServiceName + step.Position.ToString();
            ItineraryResolvers resolvers = this.ItineraryData.ResolverGroups.Where<ItineraryResolvers>(delegate(ItineraryResolvers item)
            {
                return (item.serviceId == id);
            }).FirstOrDefault<ItineraryResolvers>();
            if (resolvers != null)
            {
                this.ParseResolversIntoStep(step, resolvers.Value);
            }
        }

        private void ParseResolversIntoStep(IItineraryStep step, string value)
        {
            if (value != null)
            {
                bool flag = true;
                while (flag)
                {
                    int index = value.IndexOf(resolverDelimeter);
                    if (index != -1)
                    {
                        string str = value.Substring(0, index + resolverDelimeter.Length).Replace(resolverStartInd, "").Replace(resolverDelimeter, "").Replace("&amp;", "&");
                        if (str.Length > 1)
                        {
                            step.ResolverCollection.Add(str);
                        }
                        value = value.Substring(index + resolverDelimeter.Length).Trim();
                    }
                    else
                    {
                        index = value.IndexOf(resolverStrdelimeter);
                        if (index != -1)
                        {
                            string str2 = value.Substring(0, index + resolverStrdelimeter.Length).Replace(resolverStrStartInd, "").Replace(resolverStrdelimeter, "").Replace("&amp;", "&");
                            if (str2.Length > 1)
                            {
                                step.ResolverCollection.Add(str2);
                            }
                            value = value.Substring(index + resolverStrdelimeter.Length).Trim();
                            continue;
                        }
                        flag = false;
                    }
                }
            }
        }

        private bool HasNextService(Microsoft.Practices.ESB.Itinerary.OM.V2.Stages stage)
        {
            if (this.HasNextService())
            {
                if (stage == Microsoft.Practices.ESB.Itinerary.OM.V2.Stages.notSpecified)
                {
                    return true;
                }
                if (string.IsNullOrEmpty(this.ItineraryData.ServiceInstance.nextId))
                {
                    int index = this.ItineraryData.ServiceInstance.position + 1;
                    return (this.ItineraryData.Services[index].Service.stage == stage);
                }
                if (this.ItineraryData.itineraryDictionary.ContainsKey(this.ItineraryData.ServiceInstance.nextId))
                {
                    return (this.ItineraryData.itineraryDictionary[this.ItineraryData.ServiceInstance.nextId].stage == stage);
                }
            }
            return false;
        }

        private ItineraryServicesService ValidateIds()
        {
            ItineraryServicesService result = this.ItineraryData.Services.Where<Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices>(delegate(Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices service)
            {
                return (service.Service.id == this.ItineraryData.ServiceInstance.id);
            }).Select<Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices, ItineraryServicesService>(delegate(Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices service)
            {
                return service.Service;
            }).FirstOrDefault<ItineraryServicesService>();
            this.ValidateServiceInstance(result);
            if (result == null)
            {
                throw new ItineraryOMException(BizTalk.ESB.Extensions.ItineraryOM.Properties.Resources.ServiceInstanceNotFound, new object[] { this.ItineraryData.ServiceInstance.id });
            }
            Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices[] services = this.ItineraryData.Services;
            for (int i = 0; i < services.Length; i++)
            {
                Func<Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices, bool> predicate = null;
                Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices item = services[i];
                if ((item != null) && (item.Service != null))
                {
                    if (string.IsNullOrEmpty(item.Service.id) || string.IsNullOrEmpty(item.Service.nextId))
                    {
                        throw new ItineraryOMException(BizTalk.ESB.Extensions.ItineraryOM.Properties.Resources.ServiceIdNextIdRequired, new object[] { item.Service.name });
                    }
                    if (item.Service.nextId != Guid.Empty.ToString())
                    {
                        if (predicate == null)
                        {
                            predicate = delegate(Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices service)
                            {
                                return service.Service.id == item.Service.nextId;
                            };
                        }
                        result = this.ItineraryData.Services.Where<Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices>(predicate).Select<Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices, ItineraryServicesService>(delegate(Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices service)
                        {
                            return service.Service;
                        }).FirstOrDefault<ItineraryServicesService>();
                        if (result == null)
                        {
                            throw new ItineraryOMException(BizTalk.ESB.Extensions.ItineraryOM.Properties.Resources.ServiceInstanceNotFound, new object[] { item.Service.nextId });
                        }
                    }
                }
            }
            return result;
        }

        private void ValidateResolver(DefaultItineraryStep step, Microsoft.Practices.ESB.Itinerary.OM.V2.ItineraryServices item)
        {
            string serviceId = item.Service.name + item.Service.position.ToString();
            string str = this.ItineraryData.ResolverGroups.Where<ItineraryResolvers>(delegate(ItineraryResolvers resolverItem)
            {
                return (resolverItem.serviceId == serviceId);
            }).Select<ItineraryResolvers, string>(delegate(ItineraryResolvers resolverItem)
            {
                return resolverItem.Value;
            }).FirstOrDefault<string>();
            if (str != null)
            {
                this.ParseResolversIntoStep(step, str);
                foreach (string str2 in step.ResolverCollection)
                {
                    ResolverInfo resolverInfo = ResolverMgr.GetResolverInfo(ResolutionType.Endpoint, str2);
                    if (!resolverInfo.Success)
                    {
                        throw new ItineraryOMException(BizTalk.ESB.Extensions.ItineraryOM.Properties.Resources.ResolverInvalid, new object[] { serviceId });
                    }
                    if (ResolverMgr.GetFacts(resolverInfo.Config, resolverInfo.Resolver).Count < 1)
                    {
                        throw new ItineraryValidateException(0x7186b, new object[] { serviceId });
                    }
                }
                if (step.ResolverCollection.Count > 0)
                {
                    item.Service.resolve = true;
                }
            }
        }

        private void ValidateService(ItineraryServicesService service)
        {
            if ((service != null) && (((!service.isRequestResponseSpecified || string.IsNullOrEmpty(service.name)) || ((service.position < 0) || !service.positionSpecified)) || (string.IsNullOrEmpty(service.state) || string.IsNullOrEmpty(service.type))))
            {
                throw new ItineraryOMException(BizTalk.ESB.Extensions.ItineraryOM.Properties.Resources.ServiceInvalid, new object[] { service.name, service.position });
            }
        }

        private ItineraryServicesService ValidateServiceInstance(ItineraryServicesService result)
        {
            if ((result != null) && ((((this.ItineraryData.ServiceInstance == null) || (result.name != this.ItineraryData.ServiceInstance.name)) || ((result.position != this.ItineraryData.ServiceInstance.position) || (result.state != this.ItineraryData.ServiceInstance.state))) || ((result.stageSpecified != this.ItineraryData.ServiceInstance.stageSpecified) || (result.stage != this.ItineraryData.ServiceInstance.stage))))
            {
                throw new ItineraryOMException(BizTalk.ESB.Extensions.ItineraryOM.Properties.Resources.ServiceInstanceMisMatch);
            }
            return result;
        }

        private ItineraryProperty FindProperty(string name)
        {
            if ((this.ItineraryData.PropertyBag != null) && (this.ItineraryData.PropertyBag.Length != 0))
            {
                return this.ItineraryData.PropertyBag.Where<ItineraryProperty>(delegate(ItineraryProperty prop)
                {
                    return ((prop != null) && (prop.name == name));
                }).FirstOrDefault<ItineraryProperty>();
            }
            return null;
        }

        #endregion
    }
}
